package com.yunxin.admin.system.domain.model.user.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yunxin.admin.system.application.assembler.UserAssembler;
import com.yunxin.admin.system.application.dto.UserImportDTO;
import com.yunxin.admin.system.domain.model.user.User;
import com.yunxin.admin.system.domain.model.user.UserRepository;
import com.yunxin.admin.system.domain.model.user.UserRoleRepository;
import com.yunxin.admin.system.infra.common.constant.SystemConstants;
import com.yunxin.admin.system.infra.common.enums.GenderEnum;
import com.yunxin.admin.system.infra.common.enums.StatusEnum;
import com.yunxin.admin.system.infra.framework.easyexcel.MyAnalysisEventListener;
import com.yunxin.admin.system.infra.persistence.entity.SysRoleDO;
import com.yunxin.admin.system.infra.persistence.entity.SysUserDO;
import com.yunxin.admin.system.infra.persistence.mapper.SysRoleMapper;
import com.yunxin.admin.system.infra.persistence.mapper.SysUserMapper;
import com.yunxin.common.base.IBaseEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.List;

/**
 * 用户导入监听器
 * <p>
 * 最简单的读监听器：https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read
 *
 * @author zero°
 * @since 2023-05-22
 */
@Slf4j
public class UserImportListener extends MyAnalysisEventListener<UserImportDTO> {


    /**
     * 有效条数
     */
    private int validCount;

    /**
     * 无效条数
     */
    private int invalidCount;

    /**
     * 导入返回信息
     */
    StringBuilder msg = new StringBuilder();

    /**
     * 部门ID
     */
    private final Long deptId;

    private final SysUserMapper sysUserMapper;

    private final PasswordEncoder passwordEncoder;

    private final UserAssembler userAssembler;

    private final SysRoleMapper sysRoleMapper;

    private final UserRepository userRepository;

    private final UserRoleRepository userRoleRepository;

    public UserImportListener(Long deptId) {
        this.deptId = deptId;
        this.sysUserMapper = SpringUtil.getBean(SysUserMapper.class);
        this.passwordEncoder = SpringUtil.getBean(PasswordEncoder.class);
        this.sysRoleMapper = SpringUtil.getBean(SysRoleMapper.class);
        this.userRoleRepository = SpringUtil.getBean(UserRoleRepository.class);
        this.userRepository = SpringUtil.getBean(UserRepository.class);
        this.userAssembler = SpringUtil.getBean(UserAssembler.class);
    }

    /**
     * 每一条数据解析都会来调用
     * <p>
     * 1. 数据校验；全字段校验
     * 2. 数据持久化；
     *
     * @param userImportDTO   userImportDTO
     * @param analysisContext analysisContext
     */
    @Override
    public void invoke(UserImportDTO userImportDTO, AnalysisContext analysisContext) {
        log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportDTO));
        // 校验数据
        StringBuilder validationMsg = new StringBuilder();

        String username = userImportDTO.getUsername();
        if (CharSequenceUtil.isBlank(username)) {
            validationMsg.append("用户名为空；");
        } else {
            long count = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUserDO>().eq(SysUserDO::getUsername, username));
            if (count > 0) {
                validationMsg.append("用户名已存在；");
            }
        }

        String nickname = userImportDTO.getNickname();
        if (CharSequenceUtil.isBlank(nickname)) {
            validationMsg.append("用户昵称为空；");
        }

        String mobile = userImportDTO.getMobile();
        if (CharSequenceUtil.isBlank(mobile)) {
            validationMsg.append("手机号码为空；");
        } else {
            if (!Validator.isMobile(mobile)) {
                validationMsg.append("手机号码不正确；");
            }
            long count = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUserDO>().eq(SysUserDO::getMobile, mobile));
            if (count > 0) {
                validationMsg.append("手机号已存在；");
            }
        }

        if (validationMsg.isEmpty()) {
            // 校验通过，持久化至数据库
            User entity = userAssembler.formUserImportDTO(userImportDTO);
            // 部门
            entity.setDeptId(deptId);
            // 性别翻译
            String genderLabel = userImportDTO.getGender();
            if (CharSequenceUtil.isNotBlank(genderLabel)) {
                Integer genderValue = (Integer) IBaseEnum.getValueByLabel(genderLabel, GenderEnum.class);
                entity.setGender(genderValue);
            }

            // 角色解析
            String roleCodes = userImportDTO.getRoleCodes();
            List<Long> roleIds = null;
            if (CharSequenceUtil.isNotBlank(roleCodes)) {
                roleIds = sysRoleMapper.selectList(
                                new LambdaQueryWrapper<SysRoleDO>()
                                        .in(SysRoleDO::getCode, roleCodes.split(","))
                                        .eq(SysRoleDO::getStatus, StatusEnum.ENABLE.getValue())
                                        .select(SysRoleDO::getId)
                        ).stream()
                        .map(SysRoleDO::getId)
                        .toList();
            }


            boolean saveResult = userRepository.saveUser(entity, passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD));
            if (saveResult) {
                validCount++;
                // 保存用户角色关联
                if (CollUtil.isNotEmpty(roleIds)) {
                    userRoleRepository.saveUserRoles(entity.getId(), roleIds);
                }
            } else {
                invalidCount++;
                msg.append("第").append(validCount + invalidCount).append("行数据保存失败；<br/>");
            }
        } else {
            invalidCount++;
            msg.append("第").append(validCount + invalidCount).append("行数据校验失败：").append(validationMsg).append("<br/>");
        }
    }


    /**
     * 所有数据解析完成会来调用
     *
     * @param analysisContext analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }


    @Override
    public String getMsg() {
        // 总结信息
        return CharSequenceUtil.format("导入用户结束：成功{}条，失败{}条；<br/>{}", validCount, invalidCount, msg);
    }
}
